﻿Imports System.Text
Imports Kairyu.DCEngine
Imports System.Reflection

''' <summary>
''' DBからモデルを取得します
''' </summary>
''' <remarks></remarks>
Public Class Loader

    Public Sub New(cn As IDbConnection, prefix As String)
        Me.Connection = cn
        Me.ParameterPrefix = prefix
    End Sub

    Private _connection As IDbConnection
    ''' <summary>
    ''' コネクション
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Connection As IDbConnection
        Get
            Return _connection
        End Get
        Friend Set(value As IDbConnection)
            _connection = value
        End Set
    End Property

    Private _parameterPrefix As String
    ''' <summary>
    ''' パラメーター接頭語
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property ParameterPrefix As String
        Get
            Return _parameterPrefix
        End Get
        Private Set(ByVal value As String)
            _parameterPrefix = value
        End Set
    End Property

    ''' <summary>
    ''' クエリを取得します
    ''' </summary>
    ''' <typeparam name="T"></typeparam>
    ''' <returns></returns>
    ''' <remarks>
    ''' </remarks>
    Private Function ToQuery(Of T)() As Query(Of T)
        Dim q As New Query(Of T)(New QueryProvider(Me))
        Return q
    End Function

    ''' <summary>
    ''' クエリを取得します
    ''' </summary>
    ''' <typeparam name="T"></typeparam>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Load(Of T)() As Query(Of T)
        Return Me.ToQuery(Of T)()
    End Function

    ''' <summary>
    ''' インスタンスから主キー検索条件を設定
    ''' </summary>
    ''' <typeparam name="T"></typeparam>
    ''' <param name="instance"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Load(Of T)(instance As T) As Query(Of T)
        Return Me.ToQuery(Of T).IdSearch({instance})
    End Function

    ''' <summary>
    ''' インスタンスから主キー検索条件を設定
    ''' </summary>
    ''' <typeparam name="T"></typeparam>
    ''' <param name="instances"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Load(Of T)(instances As IEnumerable(Of T)) As IList(Of T)
        Return Me.ToQuery(Of T).IdSearch(instances).ToList
    End Function

    ''' <summary>
    ''' DBコマンドを作成します
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CreateCommand() As IDbCommand
        Return Me.CreateCommand(String.Empty)
    End Function

    ''' <summary>
    ''' DBコマンドを作成します
    ''' </summary>
    ''' <param name="text"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overridable Function CreateCommand(text As String) As IDbCommand
        Dim cmd = Me.Connection.CreateCommand
        cmd.CommandText = text
        Return cmd
    End Function

    ''' <summary>
    ''' SELECTコマンドを生成します
    ''' </summary>
    ''' <param name="tmap"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Friend Function BuildSelectCommand(tmap As RootTableMap) As IDbCommand
        Dim cmd = Me.CreateCommand

        Dim wsql As New StringBuilder
        Dim wcnt As Integer = 0

        '条件文字列
        For Each condition In tmap.Query.Conditions
            Dim s = condition.BuildSql(
                Function(val)
                    Dim pname = Me.ParameterPrefix & "W" & wcnt
                    cmd.AddParameter(pname, val)
                    wcnt += 1
                    Return pname
                End Function)

            'OR結合
            wsql.AppendDelimiter(" OR ").Append(s)
        Next
        If wsql.Any Then wsql.Insert(0, "WHERE ")

        'SQL生成
        'SELECT句、FROM句はTableMapが作成し、WHERE句はLoaderが作成する
        Dim sql As New StringBuilder
        sql.Append(tmap.ToSelectQuery)
        If wsql.Any Then
            sql.AppendLine()
            sql.Append(wsql.ToString)
        End If
        cmd.CommandText = sql.ToString

        Return cmd
    End Function

End Class
